package com.iyue.sso.helper;

import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.iyue.SpringHelper;
import com.iyue.framework.secu.Compress64;
import com.iyue.framework.secu.DES;
import com.iyue.framework.secu.base64.Base64;
import com.iyue.framework.util.ByteUtil;
import com.iyue.sso.bean.SSOInfo;
import com.iyue.sso.bean.SSOSecret;

public class SSOUtil {

	private static String ENC_U8 = "UTF-8";

	/**
	 * 登录成功
	 */
	public static final Integer LOGIN_SUCCESS = 1;
	/**
	 * 登录失败
	 */
	public static final Integer LOGIN_FAILURE = 2;

	/**
	 * 弱密码
	 */
	public static final Integer LOGIN_RUO_PRASSWORD = -2;
	/**
	 * 登录失败 - 帐号输入为空
	 */
	public static Integer LOGIN_FAILURE_NO = 3;
	/**
	 * 登录失败 - 帐号有误
	 */
	public static final Integer LOGIN_FAILURE_NOEXIST = 4;

	/**
	 * 登录失败 -此账号未注册
	 */
	public static final Integer LOGIN_FAILURE_N_REG = 7;

	/**
	 * 用户可逆密码
	 * 
	 * @param source
	 * @return
	 */
	public static String encrypt(String source) {
		SSOSecret secret = (SSOSecret) SpringHelper.getBean("SecretInfo");
		return SSOUtil.desEnc(source, secret.getSecret(), secret.getIvkey());
	}

	/**
	 * 获取M值
	 * 
	 * @param request
	 * @return
	 */
	public static String getVf(HttpServletRequest request) {
		SSOInfo info = getSSO(request);
		if (info == null) {
			return null;
		}

		String vf = encode(info);

		return vf;
	}

	/**
	 * 获取SSO认证信息
	 * 
	 * @param request
	 * @return
	 */
	public static SSOInfo getSSO(HttpServletRequest request) {
		SSOInfo info = (SSOInfo) request.getAttribute("SSO");
		return info;
	}

	/**
	 * 生成一个新的认证信息
	 * 
	 * @param account
	 * @param username
	 * @param timeSpan
	 * @return
	 */
	public static SSOInfo getSSOInfo(Integer username, long timeSpan) {
		timeSpan = timeSpan * 1000;
		SSOInfo info = new SSOInfo();
		Date date = new Date(System.currentTimeMillis() + timeSpan);
		System.out.println(date);
		info.setExpire(date);
		info.setUsername(username);

		return info;
	}

	/**
	 * 解密
	 * 
	 * @param sso
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static SSOInfo decode(String sso) {
		if (sso == null || sso.length() <= 0) {
			return null;
		}

		try {
			sso = sso.trim();
			sso = sso.replace("-", "/");
			sso = sso.replace(" ", "+");
			sso = sso.replace(";", "=");
			sso = sso.replace("*", "+");

			SSOInfo info = new SSOInfo();
			String encode = sso;
			String[] ssoEncs = encode.split("_");
			if (ssoEncs.length < 2) {
				return null;
			}

			Integer username = new Integer(ssoEncs[1]);

			info.setValid(true);

			SSOSecret secret = (SSOSecret) SpringHelper.getBean("SecretInfo");
			String decode = desDec(ssoEncs[0], secret.getSecret(), secret
					.getIvkey());
			String[] decodes = decode.split("\\|");
			if (decodes.length < 2) {
				return info;
			}

			Date expire = timeDec(decodes[0]);
			info.setExpire(expire);

			Integer uid = Integer.valueOf(Compress64.UnCompressNumber(
					decodes[1]).toString());
			info.setUsername(uid);

			if (!uid.equals(username)) {
				return null;
			}

			return info;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	/**
	 * 加密
	 * 
	 * @param info
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String encode(SSOInfo info) {

		try {
			// 生成数据串
			StringBuffer sb = new StringBuffer();
			// sb.append(Compress64.CompressNumber(info.getAccount(), 6));
			// sb.append("|");
			Date date = info.getExpire();
			if (date == null) {
				Long timeSpan = 60 * 60 * 24 * 30l;
				date = new Date(System.currentTimeMillis() + timeSpan * 1000);
			}
			sb.append(timeEnc(date));
			sb.append("|");
			sb.append(Compress64.CompressNumber(info.getUsername(), 6));

			String udata = sb.toString();

			SSOSecret secret = (SSOSecret) SpringHelper.getBean("SecretInfo");
			String ssoEnc = desEnc(udata, secret.getSecret(), secret.getIvkey());

			// String check = ssoEnc + secret.getSecret();// SSOInfo.SECRET;
			// CRC32 crc = new CRC32();
			// byte[] checkData = check.getBytes(ENC_U8);
			// crc.update(checkData);

			StringBuffer ret = new StringBuffer();
			ret.append(ssoEnc);
			ret.append("_");
			ret.append(info.getUsername());

			// return ret.toString();

			return ret.toString().replace("/", "-").replace("=", ";").replace(
					"+", "*");

		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	/**
	 * 对时间进行压缩
	 * 
	 * @param time
	 * @return
	 */
	public static String timeEnc(Date time) {
		Long current = time.getTime();
		Long base = 1262275200000l;

		Long tick = current - base;
		Long num = tick / 1000;
		return Compress64.CompressNumber(num, 6);
	}

	/**
	 * 解压缩时间
	 * 
	 * @param time
	 * @return
	 */
	public static Date timeDec(String time) {
		Long num = Compress64.UnCompressNumber(time);
		num = num * 1000 + 1262275200000l;

		return new Date(num);
	}

	/**
	 * des加密
	 * 
	 * @param source
	 * @param secret
	 * @param ivkey
	 * @return
	 */
	public static String desEnc(String source, String secret, String ivkey) {
		if (ivkey == null) {
			return null;
		}
		if (secret == null) {
			return null;
		}

		DES des = new DES();
		byte[] iv = ByteUtil.getKeyByStr(ivkey);
		String deskey = secret;
		String strbase64 = null;
		try {
			strbase64 = new String(Base64.encode(des.encryptByDES(source
					.getBytes(ENC_U8), ByteUtil.getKeyByStr(deskey), iv)),
					ENC_U8);
			System.out.println(strbase64);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return strbase64;
	}

	/**
	 * des解密
	 * 
	 * @param source
	 * @param secret
	 * @param ivkey
	 * @return
	 */
	public static String desDec(String source, String secret, String ivkey) {
		if (ivkey == null) {
			return null;
		}
		if (secret == null) {
			return null;
		}

		DES des = new DES();
		byte[] iv = ByteUtil.getKeyByStr(ivkey);
		String deskey = secret;
		String ret = null;
		try {
			ret = new String(des.decryptByDES(Base64.decode(source
					.getBytes(ENC_U8)), ByteUtil.getKeyByStr(deskey), iv),
					ENC_U8);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return ret;
	}

	/**
	 * 自动登录
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public static SSOInfo auto(HttpServletRequest request,
			HttpServletResponse response) {

		SSOInfo info = null;

		// 从URL参数中获取
		String sso = request.getParameter("vf");
		System.out.println("sso_decode=" + sso);
		if (sso == null || sso.length() <= 0) {
			// 从Cookie中获取
			sso = CookieUtil.getAuth(request);
		}

		info = SSOUtil.decode(sso);

		if (info == null) {
			System.out.println("info===null");
			return null;
		}

		if (!info.getValid()) {
			System.out.println("info.getValid()===false");
			return null;
		}

		request.setAttribute("SSO", info);

		return info;

	}

	// /**
	// * 白名单登录
	// *
	// * @param request
	// * @param response
	// * @return
	// */
	// public static SSOInfo cmccLogin(HttpServletRequest request,
	// HttpServletResponse response) {
	// String mobile = Mobile.cmcc(request);
	// if (mobile == null || mobile.length() <= 0) {
	// return null;
	// }
	// UserAccountAPI accountApi = (UserAccountAPI) SpringHelper
	// .getBean("UserAccountAPI");
	// String username = accountApi.getUserId(mobile);
	// if (username == null || username.length() <= 0) {
	// return null;
	// }
	//
	// UserInfo user = Util.getUserInfoCache(Long.valueOf(username));
	// if (user == null) {
	// return null;
	// }
	// Long timeSpan = 60 * 60 * 24 * 30l;
	// SSOInfo info = SSOUtil.getSSOInfo(Long.parseLong(mobile), Long
	// .valueOf(username), timeSpan);
	//
	// return info;
	// }

	/**
	 * 登录
	 * 
	 * @param request
	 * @param response
	 * @param info
	 */
	public static void login(HttpServletRequest request,
			HttpServletResponse response, SSOInfo info) {

		request.setAttribute("SSO", info);
		// 加密
		String auth = encode(info);
		// 记录cookie
		CookieUtil.setAuth(response, auth);
	}

}
